//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "aura.h"
#include "win32.h"
#include "private.h"

#define HUNDREDNANOSECOND2MILLIONSECOND 10000 

AURA_API AuraSystem_GetTime(
        /* [out] */ Aura_SystemTime * pTime)
{
    SYSTEMTIME systime;

    assert(NULL != pTime);

    memset(&systime, 0, sizeof(systime));
    GetSystemTime(&systime);
    WinSysTimeConvertToAura(&systime, pTime);

    return AURA_NOERROR;
}

AURA_API AuraSystem_SetTime(
        /* [in] */ Aura_SystemTime * pTime)
{
    SYSTEMTIME systime;
    BOOL bSuccess = FALSE;

    assert(NULL != pTime);

    memset(&systime, 0, sizeof(systime));
    AuraSysTimeConvertToWin(pTime, &systime);
    bSuccess = SetSystemTime(&systime);
    if (!bSuccess) {
        return GetLastECodeError();
    }

    return AURA_NOERROR;
}

AURA_API AuraSystem_QueryPerformanceCounter(
        /* [out] */Aura_Int64 * pCounter)
{
    BOOL bSuccess = FALSE;

    assert (NULL != pCounter);

    bSuccess = QueryPerformanceCounter((LARGE_INTEGER *)pCounter);
    if (!bSuccess) {
        return GetLastECodeError();
    }

    return AURA_NOERROR;
}

AURA_API AuraSystem_QueryPerformanceFrequency(
        /* [out] */Aura_Int64 * pFrequency)
{
    BOOL bSuccess = FALSE;

    assert (NULL != pFrequency);

    bSuccess = QueryPerformanceFrequency((LARGE_INTEGER*)pFrequency);
    if (!bSuccess) {
        return GetLastECodeError();
    }

    return AURA_NOERROR;
}

DWORD g_dwStartTickCount;
ULONGLONG g_lStartIdleCount;

AURA_API AuraSystem_GetElapsedTime(
        /* [out] */ Aura_Millisecond32 * pTime)
{
    assert(NULL != pTime);
    *pTime = GetTickCount() - g_dwStartTickCount;
    return AURA_NOERROR;
}

AURA_API AuraSystem_GetIdleTime(
        /* [out] */ Aura_Millisecond32 * pTime)
{
    FILETIME idletime;
    ULONGLONG curIdleCount;
    BOOL bSucc = TRUE;

    assert(NULL != pTime);

    bSucc = GetSystemTimes(&idletime, NULL, NULL);
    if (!bSucc) {
        return GetLastECodeError();
    }
    curIdleCount = idletime.dwHighDateTime;
    curIdleCount = curIdleCount << 32;
    curIdleCount |= idletime.dwLowDateTime;
    *pTime = (Aura_Millisecond32)((curIdleCount - g_lStartIdleCount)
                                   / HUNDREDNANOSECOND2MILLIONSECOND);

    return AURA_NOERROR;
}

AURA_API AuraSystem_GetMemorySizes(
        /* [out] */ Aura_Int32 * pTotalPhysicalMemorySize,
        /* [out] */ Aura_Int32 * pAvailablePhysicalMemorySize)
{
    MEMORYSTATUS memoryStatus;

    if ((NULL == pTotalPhysicalMemorySize)
        && (NULL == pAvailablePhysicalMemorySize)) {
        return AURA_E_INVALID_ARGUMENT;
    }

    GlobalMemoryStatus(&memoryStatus);
    if (NULL != pTotalPhysicalMemorySize) {
        *pTotalPhysicalMemorySize = memoryStatus.dwTotalPhys;
    }
    if (NULL != pAvailablePhysicalMemorySize) {
        *pAvailablePhysicalMemorySize = memoryStatus.dwAvailPhys;
    }

    return AURA_NOERROR;
}

AURA_API AuraSystem_ErrorPrint(
        /* [in] */ Aura_PWChar wstr)
{
    DWORD dwByteWrited=0, dwRes = 0;
    int nLen = wcslen((wchar_t *)wstr);
    char *str = (char *)_alloca(nLen);

    wcstombs(str, (const wchar_t *)wstr, nLen);

    dwRes = WriteFile(GetStdHandle(STD_ERROR_HANDLE),
                    (void *)str,
                    nLen,
                    &dwByteWrited,
                    NULL);
    if (!dwRes) {
        return GetLastECodeError();
    }
    return AURA_NOERROR;
}

AURA_API AuraSystem_TryWaitForAnyEvent(
        /* [in] */ Aura_Int32 nCount,
        /* [in] */ const Aura_Handle * pEvents,
        /* [in] */ Aura_Int32 msTimeout,
        /* [out] */ Aura_WaitResult * pResult,
        /* [out] */ Aura_Int32 * pIndex,
        /* [out] */ Aura_EventState * pState)
{
    return AURA_NOERROR;
}
